#include "events.h"
#include "substract_network.h"
#include "virtual_network.h"

#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;

#define MOST_PRIZE_FIRST 1
#define ARRIVAL_ORDER 2

#define GREEDY 1
#define TABU_SEARCH 2

int main( int argc, char** argv ){
	
	//cout << 0 << " " << 0 << endl;
	//return 0;
	
	if( argc < 3 ){
		cout << "Use ./main <priority_system><allocation_system>[v]" << endl;
		return -1;
	}
	
	int priority_system;
	int allocation_system;
	string verbose = "";
	sscanf( argv[1], "%d", &priority_system );
	sscanf( argv[2], "%d", &allocation_system );
	
	
	Events events;
	int total_requests = 0;
	int total_prizes = 0;
	
	SubstractNetwork *sn;
	if( argc == 4 )
		sn = new SubstractNetwork( "SN/sn.net", argv[3] );
	else
		sn = new SubstractNetwork( "SN/sn.net" );
	
	switch( priority_system ){
		case MOST_PRIZE_FIRST:{
			sn->setPrioritySystem( SubstractNetwork::MostPrizeFirst );
			break;
		}
		case ARRIVAL_ORDER:{
			sn->setPrioritySystem( SubstractNetwork::ArrivalOrder );
			break;
		}
		default:{
			cerr << "Error in main function: Undefined priority system" << endl;
			return(-1);
		}
	}
	
	switch( allocation_system ){
		case GREEDY:{
			sn->setAllocationSystem( SubstractNetwork::Greedy );
			break;
		}
		case TABU_SEARCH:{
			sn->setAllocationSystem( SubstractNetwork::TabuSearch );
			break;
		}
		default:{
			cerr << "Error in main function: Undefined allocation system" << endl;
			return(-1);
		}
	}
	
	while( events.eventsLeft() ){
		struct event evt = events.getNextEvent();
		switch( evt.type ){
			case 'A':{
				//insert the incoming vn network request on the queue of substract network
				string in_vn( "VNs/vn" );
				char vn_id[10];
				sprintf( vn_id, "%d.net", evt.vn_id );
				in_vn.append( vn_id );
				VirtualNetwork *vn = new VirtualNetwork( in_vn.c_str() );
				sn->pushInScheduleQueue( vn, evt.vn_id );
				total_prizes += vn->getPrize();
				++total_requests;
				break;
			}
			case 'D':{
				//deallocate resources on substract network assigned to VN evt.vn_id
				sn->deallocateVirtualNetwork( evt.vn_id );
				break;
			}
			case 'E':{
				//remove the VN with id evt.vn_id from the substract network queue - the request was denied
				sn->popFromScheduleQueue( evt.vn_id );
				break;
			}
			case 'S':{
				//calls substract network schedule algorithm passing evt.time
				sn->scheduler();
				break;
			}
			default:{
				cerr << "Error in main function: Undefined event type." << endl;
				return(-1);
			}
		}
	}
	
	int sum_prizes_attended_requests = sn->getSumPrizesAttendedRequests();
	int total_attended_requests = sn->getTotalAttendedRequests();
	
	//cout << "Total requests: " << total_requests << endl;
	//cout << "Requests attended: " << total_attended_requests << endl;
	//cout << "Sum prizes: " << sum_prizes_attended_requests << endl;
	
	cout << (float)total_attended_requests / (float)total_requests << " " << (float)sum_prizes_attended_requests / (float)total_prizes;
	
	delete sn;
	
	return 0;
}